/* Copyright (c) 2004-2022 peigen.info. All rights reserved. */

package info.peigen.hotpot.common.core.enums;

import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <b>(CountryCode)</b>
 * 国家地区代码
 *
 * @author Peigen
 * @version 1.0.0
 * @since 2021/4/12
 */
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum CountryCode {
    /** 为了对抗 Alibaba Java Coding 而存在的注释 */
    CN("CN", "CHN", "156", "中华人民共和国"),
    HK("HK", "HKG", "344", "中国香港"),
    TW("TW", "TWN", "158", "中国台湾省"),
    US("US", "USA", "840", "美国"),
    GB("GB", "GBR", "826", "英国"),
    DE("DE", "DEU", "276", "德国"),
    TH("TH", "THA", "764", "泰国"),
    FR("FR", "FRA", "250", "法国"),
    IT("IT", "ITA", "380", "意大利"),
    CA("CA", "CAN", "124", "加拿大"),
    IN("IN", "IND", "356", "印度"),
    ES("ES", "ESP", "724", "西班牙"),
    AU("AU", "AUS", "036", "澳大利亚"),
    SG("SG", "SGP", "702", "新加坡"),
    MY("MY", "MYS", "458", "马来西亚"),
    ID("ID", "IDN", "360", "印尼"),

    JP("JP", "JPN", "392", "日本"),
    /** 不晓得啷格回事 */
    UNKNOWN("--", "--", "000", "卡卡共和国"),

    ;

    /** 二位字母代码 基于 ISO 3166-1 alpha-2 */
    private String twoCode;

    /** 三位字母代码 基于 ISO 3166-1 alpha-3 */
    private String threeCode;

    /** 三位数字码，基于 ISO 3166-1 numeric */
    private String threeNumber;

    /** 国家名 */
    private String countryName;

    /**
     * 通过枚举<code>code</code>获得枚举
     *
     * @param code 枚举值
     *
     * @return CountryCode
     */

    public static CountryCode getByCode(String code) {
        return Stream.of(values())
                .filter(innerEnum -> StrUtil.equals(code, innerEnum.getTwoCode()))
                .findFirst().orElse(UNKNOWN);
    }

    /**
     * 通过枚举<code>name</code>获得枚举
     *
     * @param name 枚举名
     *
     * @return CountryCode
     */
    public static CountryCode getByName(String name) {
        return Stream.of(values())
                .filter(innerEnum -> StrUtil.equalsIgnoreCase(name, innerEnum.name()))
                .findFirst().orElse(UNKNOWN);
    }

    /**
     * 获取全部枚举
     *
     * @return List<CountryCode>
     */
    public static List<CountryCode> getAllEnum() {
        return Lists.newArrayList(values());
    }

    /**
     * 获取全部枚举值
     *
     * @return List<String>
     */
    public static List<String> getAllEnumCode() {
        return getAllEnum().stream().map(CountryCode::twoCode).collect(Collectors.toList());
    }

    /**
     * 通过code获取TwoCode
     *
     * @param code 枚举值
     *
     * @return String
     */
    public static String getTwoCodeByCode(String code) {

        return Optional.ofNullable(code).map(
                str ->
                        Optional.ofNullable(getByCode(str))
                                .map(CountryCode::twoCode).orElse(UNKNOWN.twoCode())
        ).orElse(null);
    }

    /**
     * 通过code获取ThreeCode
     *
     * @param code 枚举值
     *
     * @return String
     */
    public static String getThreeCodeByCode(String code) {

        return Optional.ofNullable(code).map(
                str ->
                        Optional.ofNullable(getByCode(str))
                                .map(CountryCode::threeCode).orElse(UNKNOWN.threeCode())
        ).orElse(null);
    }

    /**
     * 通过code获取CountryName
     *
     * @param code 枚举值
     *
     * @return String
     */
    public static String getThreeNumberByCode(String code) {
        return Optional.ofNullable(code).map(
                str -> Optional.ofNullable(getByCode(str))
                        .map(CountryCode::threeNumber).orElse(UNKNOWN.threeNumber())
        ).orElse(null);
    }

    /**
     * 通过code获取CountryName
     *
     * @param code 枚举值
     *
     * @return String
     */
    public static String getCountryNameByCode(String code) {

        return Optional.ofNullable(code).map(
                str ->
                        Optional.ofNullable(getByCode(str))
                                .map(CountryCode::countryName).orElse(UNKNOWN.countryName())
        ).orElse(null);
    }

    /**
     * 获取枚举code
     *
     * @param innerEnum 枚举
     *
     * @return code
     */
    public static String getTwoCode(CountryCode innerEnum) {
        return Optional.ofNullable(innerEnum).map(CountryCode::twoCode).orElse(UNKNOWN.twoCode());
    }

    /**
     * map
     *
     * @return Map
     */
    public static Map<String, String> maps() {
        return Stream.of(values()).collect(Collectors.toMap(CountryCode::twoCode, CountryCode::countryName));
    }

    /**
     * @return Returns the twoCode.
     */
    public String twoCode() {
        return twoCode;
    }

    /**
     * @return Returns the threeCode.
     */
    public String threeCode() {
        return threeCode;
    }

    /**
     * @return Returns the threeNumber.
     */
    public String threeNumber() {
        return threeNumber;
    }

    /**
     * @return Returns the countryName.
     */
    public String countryName() {
        return countryName;
    }

}